package com.ysstech.etfmanage.service.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ysstech.common.enums.YssMarketEnum;
import com.ysstech.common.exception.BusinessException;
import com.ysstech.common.util.DateUtil;
import com.ysstech.etfmanage.entity.Param;
import com.ysstech.etfmanage.entity.ParamVo;
import com.ysstech.etfmanage.mapper.ParamMapper;
import com.ysstech.etfmanage.service.ParamService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

/**
 * <p>
 * 服务类
 * </p>
 *
 * @author lishuangliang
 * @since 2021-02-23
 */
@Slf4j
@Service
public class ParamServiceImpl extends ServiceImpl<ParamMapper, Param> implements ParamService {


    /**
     * 查询某一类参数，返回集合
     *
     * @param etfParam
     * @param tclass
     * @return
     * @throws Exception
     */
    public List<Object> getParamList(Param etfParam, Class tclass) throws Exception {
        List<Object> parameterList = new ArrayList<>();
        //不同的参数子类型
        QueryWrapper<Param> wrapper = new QueryWrapper<>();
        wrapper.select("ETF_TYPE,ETF_MODE,ETF_MARKET");
        wrapper.eq("ACCOUNT_ID", etfParam.getAccountId());
        if (null != etfParam.getEtfType()) {
            wrapper.eq("ETF_TYPE", etfParam.getEtfType());
        }
        if (null != etfParam.getEtfMode()) {
            wrapper.eq("ETF_MODE", etfParam.getEtfMode());
        }
        if (StringUtils.isNotBlank(etfParam.getEtfMarket())) {
            wrapper.eq("ETF_MARKET", etfParam.getEtfMarket());
        }
        wrapper.groupBy("ETF_TYPE,ETF_MODE,ETF_MARKET");
        List<Param> list = this.list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            log.error("没有获取到对应的ETF参数设置");
            return parameterList;
        }
        for (Param param : list) { // 多个类型的参数类型
            QueryWrapper<Param> wrapperquery = new QueryWrapper<>();
            wrapperquery.eq("ACCOUNT_ID", etfParam.getAccountId());
            wrapperquery.eq("ETF_TYPE", param.getEtfType());
            wrapperquery.eq("ETF_MODE", param.getEtfMode());
            wrapperquery.eq("ETF_MARKET", param.getEtfMarket());
            List<Param> listquery = this.list(wrapperquery);
            if (CollectionUtils.isEmpty(listquery)) {
                continue;
            }
            //创建一个新的对象
            Object obj = tclass.newInstance();
            Map<String, String> map = new HashMap<>();
            for (Param par : listquery) {
                map.put(par.getCode(), par.getValue());
            }
            map.put("etfType", String.valueOf(param.getEtfType()));
            map.put("etfMode", String.valueOf(param.getEtfMode()));
            map.put("etfMarket", param.getEtfMarket());
            getModelParam(map, tclass, obj);
            parameterList.add(obj);
        }
        return parameterList;
    }


    private void getModelParam(Map<String, String> map, Class tclass, Object obj) throws Exception {
        if (null == map || map.size() == 0) {
            throw new BusinessException("获取参数信息失败，请稍后重试！");
        }
        // 获取实体类的所有属性，返回Field数组
        Field[] field = tclass.getDeclaredFields();
        if (null == field || field.length == 0) {
            throw new BusinessException("获取对象属性值出错，请稍后重试！");
        }
        // 遍历所有属性
        for (int j = 0; j < field.length; j++) {
            // 获取属性的名字
            String name = field[j].getName();
            // 将属性的首字符大写，方便构造get，set方法
            String methodName = name.substring(0, 1).toUpperCase() + name.substring(1);
            // 获取属性的类型
            String type = field[j].getGenericType().toString();
            // 如果type是类类型，则前面包含"class "，后面跟类名
            if (type.equals("class java.lang.String")) {
                Method setMethod = tclass.getMethod("set" + methodName, String.class);
                setMethod.invoke(obj, StringUtils.isNotBlank(map.get(field[j].getName())) ? String.valueOf(map.get(field[j].getName())) : null);
                continue;
            }
            if (type.equals("class java.lang.Boolean")) {
                Method setMethod = tclass.getMethod("set" + methodName, Boolean.class);
                setMethod.invoke(obj, StringUtils.isNotBlank(map.get(field[j].getName())) ? Boolean.valueOf(map.get(field[j].getName())) : false);
                continue;
            }
            if (type.equals("class java.math.BigDecimal")) {
                Method setMethod = tclass.getMethod("set" + methodName, BigDecimal.class);
                setMethod.invoke(obj, StringUtils.isNotBlank(map.get(field[j].getName())) ? new BigDecimal(map.get(field[j].getName())) : BigDecimal.ZERO);
                continue;
            }
            if (type.equals("class java.lang.Integer")) {
                Method setMethod = tclass.getMethod("set" + methodName, Integer.class);
                setMethod.invoke(obj, StringUtils.isNotBlank(map.get(field[j].getName())) ? Integer.valueOf(map.get(field[j].getName())) : 0);
                continue;
            }
            if (type.equals("class java.lang.Date")) {
                Method setMethod = tclass.getMethod("set" + methodName, Date.class);
                setMethod.invoke(obj, StringUtils.isNotBlank(map.get(field[j].getName())) ? DateUtil.strToDate(map.get(field[j].getName())) : null);
                continue;
            }
            // 如果有需要,可以仿照上面继续进行扩充,再增加对其它类型的判断
        }
    }


    /**
     * 通过市场获取对应的参数信息
     *
     * @param market  市场代码
     * @param paramVo etf参数
     * @return
     */
    public ParamVo getEtfParamVo(String market, ParamVo paramVo) throws Exception {
        if (null == paramVo || StringUtils.isBlank(market)) {
            return paramVo;
        }
        ParamVo param = new ParamVo();
        param.setAccountId(paramVo.getAccountId());
        param.setEtfSeat(paramVo.getEtfSeat());
        param.setEtfMode(paramVo.getEtfMode());
        param.setEtfType(paramVo.getEtfType());
        param.setEtfMarket(paramVo.getEtfMarket());
        param.setEtfBenchmarkScale(paramVo.getEtfBenchmarkScale());
        YssMarketEnum yssMarketEnum = YssMarketEnum.getEnum(market);
        if (yssMarketEnum != null) {
            switch (yssMarketEnum) {
                case S:
                    param.setEtfFillSeat(paramVo.getEtfFillSeatSz()); //ETF深圳补票席位
                    param.setForceTransactionDays(paramVo.getForceTransactionDaysSz());  //强制处理证券交易天数
                    param.setForceExchangeDays(paramVo.getForceExchangeDaysSz()); //强制处理交易所交易天数
                    param.setEtfRate(paramVo.getEtfRateSz());  // ETF汇率
                    param.setCapitalCode(paramVo.getCapitalCodeSz()); // 资金代码
                    param.setEtfStartFillDate(paramVo.getEtfStartFillDateSz()); // 补票日期
                    param.setEtfRenewType(paramVo.getEtfRenewTypeSz()); // ETF台账更新方式
                    param.setEtfSecondFill(paramVo.getEtfSecondFillSz()); // ETF台账碎股二次补票
                    param.setEtfOrganizationPrice(paramVo.getEtfOrganizationPriceSz()); //行情
                    param.setPayableReplaceMoneyDays(paramVo.getPayableReplaceMoneyDaysSz());  // 应付替代款结转日期
                    break;
                case H:
                    param.setEtfFillSeat(paramVo.getEtfFillSeatSh()); //ETF上海补票席位
                    param.setForceTransactionDays(paramVo.getForceTransactionDaysSh());  //强制处理证券交易天数
                    param.setForceExchangeDays(paramVo.getForceExchangeDaysSh()); //强制处理交易所交易天数
                    param.setEtfRate(paramVo.getEtfRateSh());  // ETF汇率
                    param.setCapitalCode(paramVo.getCapitalCodeSh()); // 资金代码
                    param.setEtfStartFillDate(paramVo.getEtfStartFillDateSh()); // 补票日期
                    param.setEtfRenewType(paramVo.getEtfRenewTypeSh()); // ETF台账更新方式
                    param.setEtfSecondFill(paramVo.getEtfSecondFillSh()); // ETF台账碎股二次补票
                    param.setEtfOrganizationPrice(paramVo.getEtfOrganizationPriceSh()); //行情
                    param.setPayableReplaceMoneyDays(paramVo.getPayableReplaceMoneyDaysSh());  // 应付替代款结转日期
                    break;
                case HK:
                    param.setEtfFillSeat(paramVo.getEtfFillSeatHk()); //ETF香港补票席位
                    param.setForceTransactionDays(paramVo.getForceTransactionDaysHk());  //强制处理证券交易天数
                    param.setForceExchangeDays(paramVo.getForceExchangeDaysHk()); //强制处理交易所交易天数
                    param.setEtfRate(paramVo.getEtfRateHk());  // ETF汇率
                    param.setCapitalCode(paramVo.getCapitalCodeHk()); // 资金代码
                    param.setEtfStartFillDate(paramVo.getEtfStartFillDateHk()); // 补票日期
                    param.setEtfRenewType(paramVo.getEtfRenewTypeHk()); // ETF台账更新方式
                    param.setEtfSecondFill(paramVo.getEtfSecondFillHk()); // ETF台账碎股二次补票
                    param.setEtfOrganizationPrice(paramVo.getEtfOrganizationPriceHk()); //行情
                    param.setPayableReplaceMoneyDays(paramVo.getPayableReplaceMoneyDaysHk());  // 应付替代款结转日期
                    break;
                default:
                    throw new BusinessException("系统找不到对应的市场代码: " + yssMarketEnum.getEnum(market));
            }
        }
        return param;
    }


}
